# -*- coding: utf-8 -*-
"""
浏览器配置
@author:   XueJunJie
@file:     BrowSettings.py
@date:     2024-9-23
@version:  1.2.0.1
"""
import os
import warnings
from .BrowInfoFetch import get_chrome_path


class DriverSettings:

    def __init__(
        self,
        chromepath: str = "auto",
        driverpath: str = "chromedriver.exe",
        *args,
        proxy: str = "",
        ua: str = "",
        img: int = 0,
        headers: dict = {},
        use_user_data: bool = False,
        user_data_path: str = "",
        sandbox: bool = True,
        gpu: bool = True,
        handless: bool = False,
        slink: bool = False,
        mask: bool = False,
        debugger_address: str = "",
        chrome_arguments: list = [],
        chrome_experimental_options: dict = {},
        crx_extensions: list = [],
        optimize_setting: bool = True,
        log_path: str = None,
        custom_chrome_options: object = None,
        auto_update_chromedriver: bool = False,
        chrome_version: str = "",
        my_update: bool = False,
        chromedriver_download_proxy: dict = None,
        **kwargs,
    ) -> None:
        """
        标准初始化
        参数:
            chromepath                      str     'auto'              chrome的路径[不填则使用系统配置,'auto'则尝试自动探寻,其他直接作为参数]
            driverpath                      str     'chromedriver.exe'  chromedriver的路径[默认是运行目录下]
            *
            proxy                           str     ''                  代理 username:password@123.123.123.123:6666 或 123.123.123.123:6666
            ua                              str     ''                  自定义ua
            img                             int     0                   是否加载图片，0默认 1加载 2不加载
            headers                         dist    {}                  请求头
            use_user_data                   bool    False               是否使用用户数据
            user_data_path                  str     ''                  用户数据路径，use_user_data为True才有效
            sandbox                         bool    True                使用沙盒环境，linux无法启动chrome时应该禁止
            gpu                             bool    True                硬件加速，禁用后能减少chrome的内存占用，和加快加载速度
            handless                        bool    False               隐藏窗口，使用无窗口模式记得kill掉chrome或者使用driver.close()
            *slink                          bool    False               不提示“正在自动测试”，默认为False。在部分机器启用会导致浏览器崩溃
            mask                            bool    False               简易伪装不是driver。推荐使用
            debugger_address                str     ''                  连接chrome的调试接口地址。如"localhost:9222"。
                                                                        chrome启动时需要参数"--remote-debugging-port=9222"指定调试端口
            chrome_arguments                list    []                  chrome其他配置参数，例如["--no-sandbox", "--headless"]
            chrome_experimental_options     dict    {}                  chrome实验性配置参数，例如{"excludeSwitches": ["enable-automation"]}
            crx_extensions                  list    []                  插件路径列表
            optimize_setting                bool    True                优化chrome的配置，默认开启。非原生chrome浏览器,或使用debugger_address时建议禁止
            log_path                        str     None                server日志目录，默认没有
            ---其他参数---
            custom_chrome_options           object  None                自定义配置对象。此项非None时，除路径外其他参数无效。
            auto_update_chromedriver        bool    False               自动更新driver
            chrome_version                  str     ''                  指定chrome版本,其他基于chrome底层的浏览器需要指定
            ---特殊参数---
            my_update                       bool    False               使用自定义包装更新driver逻辑
            chromedriver_download_proxy     dict    None                下载chromedriver时使用的代理
        返回：
            无
        """
        if args:
            warnings.warn("为了未来开发兼容，除chromepath和driverpath外，其他参数不再支持匿名传参。请使用参数名传参")
        self._init_args()
        self.driverpath = driverpath
        self.proxy = proxy
        self.ua = ua
        self.img = img
        self.headers = headers
        self.use_user_data = use_user_data
        self.user_data_path = user_data_path
        self.sandbox = sandbox
        self.gpu = gpu
        self.handless = handless
        self.slink = slink
        self.mask = mask
        self.debugger_address = debugger_address
        self.chrome_arguments = chrome_arguments
        self.chrome_experimental_options = chrome_experimental_options
        self.crx_extensions = crx_extensions
        self.optimize_setting = optimize_setting
        self.log_path = log_path
        self.chromepath = chromepath
        # 其他配置
        self.custom_chrome_options = custom_chrome_options
        self.auto_update_chromedriver = auto_update_chromedriver
        self.chrome_version = chrome_version
        # **特殊配置**
        # 自动更新函数调用逻辑
        self.my_update = my_update
        self.chromedriver_download_proxy = chromedriver_download_proxy
        for k, v in kwargs.items():
            if not hasattr(self, k):
                warnings.warn(f"参数{k}={v}是无效参数")
            setattr(self, k, v)

    def _init_args(self):
        # 私有参数
        self._port = 0

    # chrome的路径
    @property
    def chromepath(self):
        return self._chromepath

    @chromepath.setter
    def chromepath(self, path: str):
        if path:
            if path == "auto":
                if self._use_user_data or self._debugger_address:
                    path = get_chrome_path()
                    assert path, "无法自动识别chrome路径"
                else:
                    path = ""
            else:
                assert os.path.isfile(path), "未找到chrome启动器"
        self._chromepath = path

    # chromedriver的路径
    @property
    def driverpath(self):
        return self._driverpath

    @driverpath.setter
    def driverpath(self, path: str):
        self._driverpath = path

    # 代理
    @property
    def proxy(self):
        return self._proxy

    @proxy.setter
    def proxy(self, value: str):
        self._proxy = value

    # UA
    @property
    def ua(self):
        return self._ua

    @ua.setter
    def ua(self, value: str):
        self._ua = value

    # 是否加载图片，0默认 1加载 2不加载
    @property
    def img(self):
        return self._img

    @img.setter
    def img(self, value: int):
        assert value in (0, 1, 2), "参数img只接受0,1,2"
        self._img = value

    # 请求头
    @property
    def headers(self):
        return self._headers

    @headers.setter
    def headers(self, value: dict):
        self._headers = value

    # 是否使用用户数据
    @property
    def use_user_data(self):
        return self._use_user_data

    @use_user_data.setter
    def use_user_data(self, flag: bool):
        self._use_user_data = flag

    # 用户数据路径
    @property
    def user_data_path(self):
        return self._user_data_path

    @user_data_path.setter
    def user_data_path(self, value: str):
        assert value == "" or os.path.isdir(value), "未找到用户数据目录"
        self._user_data_path = value

    # 使用沙盒环境
    @property
    def sandbox(self):
        return self._sandbox

    @sandbox.setter
    def sandbox(self, value: bool):
        self._sandbox = value

    # 硬件加速
    @property
    def gpu(self):
        return self._gpu

    @gpu.setter
    def gpu(self, value: bool):
        self._gpu = value

    # 隐藏窗口
    @property
    def handless(self):
        return self._handless

    @handless.setter
    def handless(self, flag: bool):
        self._handless = flag

    # 不提示“正在自动测试”，默认为False。在部分机器启用会导致浏览器崩溃
    @property
    def slink(self):
        return self._slink

    @slink.setter
    def slink(self, flag: bool):
        self._slink = flag

    # 简易伪装不是driver。推荐使用
    @property
    def mask(self):
        return self._mask

    @mask.setter
    def mask(self, flag: bool):
        self._mask = flag

    # 连接chrome的调试接口地址。如"localhost:9222"。
    # chrome启动时需要参数"--remote-debugging-port=9222"指定调试端口
    @property
    def debugger_address(self):
        return self._debugger_address

    @debugger_address.setter
    def debugger_address(self, value: str):
        if value:
            assert ":" in value, "未知debug地址"
            self._port = int(value.split(":", 1)[-1])
        self._debugger_address = value

    # chrome其他配置参数
    @property
    def chrome_arguments(self):
        return self._chrome_arguments

    @chrome_arguments.setter
    def chrome_arguments(self, value: list):
        self._chrome_arguments = value

    # chrome其他实验性参数
    @property
    def chrome_experimental_options(self):
        return self._chrome_experimental_options

    @chrome_experimental_options.setter
    def chrome_experimental_options(self, value: dict):
        self._chrome_experimental_options = value

    # 插件路径列表
    @property
    def crx_extensions(self):
        return self._crx_extensions

    @crx_extensions.setter
    def crx_extensions(self, value: list):
        self._crx_extensions = value

    # 优化配置
    # 使用debugger_address时不要开启此项
    @property
    def optimize_setting(self):
        return self._optimize_setting

    @optimize_setting.setter
    def optimize_setting(self, flag: bool):
        self._optimize_setting = flag

    # server日志目录，默认没有
    @property
    def log_path(self):
        return self._log_path

    @log_path.setter
    def log_path(self, value: str):
        self._log_path = value

    # --其他参数--
    # 是否自动更新driver
    @property
    def auto_update_chromedriver(self):
        return self._auto_update_chromedriver

    @auto_update_chromedriver.setter
    def auto_update_chromedriver(self, flag: bool):
        self._auto_update_chromedriver = flag

    # 引导下载指定版本driver
    @property
    def chrome_version(self):
        return self._chrome_version

    @chrome_version.setter
    def chrome_version(self, value: str):
        self._chrome_version = value

    # 自定义的chrome配置参数
    @property
    def custom_chrome_options(self):
        return self._custom_chrome_options

    @custom_chrome_options.setter
    def custom_chrome_options(self, value: str):
        self._custom_chrome_options = value
